function costs = cmaesParallelSplitRough(gainsPop)
    global rtp InitialGuess
    %allocate costs vector and paramsets the generation
    popSize = size(gainsPop,2);

    numTerrains = 5;
    rampSlope = 0.0025;
    [groundX, groundZ, groundTheta] = generateGround('flat');

    costs = nan(popSize*numTerrains,1);
    paramSets = cell(popSize*numTerrains,1);

    %create param sets
    gainind = 1;
    for i = 1:numTerrains:(numTerrains*popSize)
        %set gains
        Gains = InitialGuess.*exp(gainsPop(:,gainind));

        paramSets{i} = Simulink.BlockDiagram.modifyTunableParameters(rtp, ...
            'LGainGAS',          Gains( 1), ...
            'LGainGLU',          Gains( 2), ...
            'LGainHAM',          Gains( 3), ...
            'LGainKneeOverExt',  Gains( 4), ...
            'LGainSOL',          Gains( 5), ...
            'LGainSOLTA',        Gains( 6), ...
            'LGainTA',           Gains( 7), ...
            'LGainVAS',          Gains( 8), ...
            'LKglu',             Gains( 9), ...
            'LPosGainGG',        Gains(10), ...
            'LSpeedGainGG',      Gains(11), ...
            'LhipDGain',         Gains(12), ...
            'LhipPGain',         Gains(13), ...
            'LkneeExtendGain',   Gains(14), ...
            'LkneeFlexGain',     Gains(15), ...
            'LkneeHoldGain1',    Gains(16), ...
            'LkneeHoldGain2',    Gains(17), ...
            'LkneeStopGain',     Gains(18), ...
            'LlegAngleFilter',   Gains(19), ...
            'RGainGLU',          Gains(20), ...
            'RGainHAM',          Gains(21), ...
            'RKglu',             Gains(22), ...
            'RPosGainGG',        Gains(23), ...
            'RSpeedGainGG',      Gains(24), ...
            'RhipDGain',         Gains(25), ...
            'RhipPGain',         Gains(26), ...
            'RlegAngleFilter',   Gains(27), ...
            'anklePgain',        Gains(28), ...
            'ankleDgain',        Gains(29), ...
            'ankleFilterPID',    Gains(30), ...
            'ankleFilterSEA',    Gains(31), ...
            'kneePgain',         Gains(32), ...
            'kneeDgain',         Gains(33), ...
            'kneeFilterPID',     Gains(34), ...
            'kneeFilterSEA',     Gains(35), ...
            'bKneeSwing1',       Gains(36), ...
            'bKneeSwing2',       Gains(37), ...
            'k1AnkleStance1',    Gains(38), ...
            'k1AnkleStance2',    Gains(39), ...
            'k1AnkleSwing1',     Gains(40), ...
            'k1AnkleSwing2',     Gains(41), ...
            'k1KneeStance1',     Gains(42), ...
            'k1KneeStance2',     Gains(43), ...
            'k1KneeSwing1',      Gains(44), ...
            'k1KneeSwing2',      Gains(45), ...
            'k2AnkleStance1',    Gains(46), ...
            'k2KneeStance2',     Gains(47), ...
            'ankleAngleThr',     Gains(48), ...
            'phiAnkleStance1',   Gains(49), ...
            'phiAnkleStance12',  Gains(50), ...
            'phiAnkleStance2',   Gains(51), ...
            'phiKneeStance1',    Gains(52), ...
            'phiKneeStance2',    Gains(53), ...
            'phiKneeSwing1',     Gains(54), ...
            'phiKneeSwing2',     Gains(55), ...
            'legLengthClr',      Gains(56), ...
            'simbiconGainD',     Gains(57), ...
            'simbiconGainV',     Gains(58), ...
            'simbiconLegAngle0', Gains(59));

        %set ground heights
        for j = 0:(numTerrains-1)
            rng('default');
            rng(4*j);
            for k = 21:2:length(groundX)
                groundZ(k) = groundZ(k-2) + groundX(k-19)*2*(rand - 0.5)*rampSlope;
                groundZ(k+1) = groundZ(k);
            end
            %groundZ(end) = [];
            groundTheta = [atan(diff(groundZ)./diff(groundX)), 0];
    
            paramSets{i+j} = Simulink.BlockDiagram.modifyTunableParameters(paramSets{i}, ...
                'groundZ',     groundZ, ...
                'groundTheta', groundTheta);
        end
        gainind = gainind + 1;
    end
    rng('shuffle')

    %simulate each sample and store cost
    parfor i = 1:length(paramSets)
        costs(i) = evaluateCostParallel(paramSets{i})
    end

    %calculate median across terrains
    costs = reshape(costs,numTerrains,popSize)
    isinvalid = sum(isnan(costs))>1;
    costs = nanmean(costs);
    costs(isinvalid) = nan
